﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using ObjRec;

namespace FaceRecognition
{
    public partial class frmImageSetManagement : Form
    {
        List<int> _id;
        int _selectedIndex;
        Thread _loadFolderThread;
        Thread _refreshListThread;

        public frmImageSetManagement()
        {
            InitializeComponent();
        }

        private void frmImageSetManagement_Load(object sender, EventArgs e)
        {
            string types = "All supported types|";
            for (int i = 0; i < ExternalFunctions.SUPPORTED_IMAGE_TYPE.Length; i++)
            {
                if (i == 0) types += "*" + ExternalFunctions.SUPPORTED_IMAGE_TYPE[i];
                else types += ";*" + ExternalFunctions.SUPPORTED_IMAGE_TYPE[i];
            }
            openFileDialog1.Filter = types;
            _refreshListThread = new Thread(() => RefreshList());
            _refreshListThread.Start();
        }

        private void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            _selectedIndex = e.ItemIndex;
            if (listView1.SelectedItems.Count == 0)
            {
                pictureBox1.Image = null;
                textBox1.Text = "";
                textBox1.Enabled = false;
                button1.Enabled = false;
                contextMenuStrip1.Items[0].Enabled = false;
            }
            else
            {
                pictureBox1.Image = ExternalFunctions.BytesToBitmap(Form1._fr._people[_id[_selectedIndex]]._image);
                textBox1.Text = Form1._fr._people[_id[_selectedIndex]]._name;
                textBox1.Enabled = true;
                button1.Enabled = true;
                contextMenuStrip1.Items[0].Enabled = true;
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (int item in listView1.SelectedIndices)
            {
                Form1._fr._people.Remove(_id[item]);
            }
            _refreshListThread = new Thread(() => RefreshList());
            _refreshListThread.Start();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Done!");
            Form1._fr._people[_id[_selectedIndex]]._name = textBox1.Text;
            listView1.Items[_selectedIndex].Name = textBox1.Text;
        }

        private void RefreshList()
        {
            Form1._fr.Train(false);
            _id = Form1._fr._people.Keys.ToList<int>();
            ClearList();
            for (int i = 0; i < 1000 && i < Form1._fr._people.Count; i++)
            {
                AddList(Form1._fr._people[_id[i]]._name, i, ExternalFunctions.BytesToBitmap(Form1._fr._people[_id[i]]._image));
            }
            if (Form1._fr._people.Count > 1000) lblNumImages.Text = "# of images: " + Form1._fr._people.Count + " (Due to internal error, only 1000 images are shown)";
            else if (Form1._fr._people.Count > 0) lblNumImages.Text = "# of images: " + Form1._fr._people.Count;
            else lblNumImages.Text = "";
        }

        private void addFacesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                string[] filenames = openFileDialog1.FileNames;
                foreach (string s in filenames)
                {
                    string filename = s;
                    Bitmap bmp = new Bitmap(filename);
                    Dictionary<int, Person> people = Form1._fr.DetectFaces(bmp);
                    foreach (var item in people)
                    {
                        int lastkey;
                        if (Form1._fr._people.Count == 0) lastkey = 0;
                        else lastkey = Form1._fr._people.Keys.Max() + 1;
                        Person p = item.Value;
                        p._name = p._name == "" ? lastkey.ToString() : p._name;
                        Form1._fr._people.Add(lastkey, item.Value);
                    }
                    bmp.Dispose();
                }
                _refreshListThread = new Thread(() => RefreshList());
                _refreshListThread.Start();
            }
        }

        private void fromDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                string path = folderBrowserDialog1.SelectedPath;
                _loadFolderThread = new Thread((obj) => LoadFromFolder(obj));
                _loadFolderThread.Start(path);
            }
        }

        private void LoadFromFolder(object o)
        {
            int count = 0;
            string path = o.ToString();
            SetlblCurrentFile("Searching for file(s) in " + path);
            List<string> filenames = System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories).Where(s => ExternalFunctions.SUPPORTED_IMAGE_TYPE.Contains(System.IO.Path.GetExtension(s))).ToList();
            foreach (string s in filenames)
            {
                string filename = s;
                Bitmap bmp = ExternalFunctions.OpenImage(filename);
                if (bmp == null) continue;
                Dictionary<int, Person> people = Form1._fr.DetectFaces(bmp);
                foreach (var item in people)
                {
                    int lastkey;
                    if (Form1._fr._people.Count == 0) lastkey = 0;
                    else lastkey = Form1._fr._people.Keys.Max() + 1;
                    Person p = item.Value;
                    p._name = p._name == "" ? lastkey.ToString() : p._name;
                    Form1._fr._people.Add(lastkey, item.Value);
                }
                bmp.Dispose();
                count++;
                SetlblCurrentFile(count + @"/" + filenames.Count + " (" + Form1._fr._people.Count + " face(s) detected)");
                if (Form1._fr._people.Count == 6000) break;
            }
            SetlblCurrentFile("");
            _refreshListThread = new Thread(() => RefreshList());
            _refreshListThread.Start();
        }

        private delegate void SetlblCurrentFileDelegate(string s);
        private void SetlblCurrentFile(string s)
        {
            if (this.statusStrip1.InvokeRequired)
            {
                SetlblCurrentFileDelegate d = new SetlblCurrentFileDelegate(SetlblCurrentFile);
                this.Invoke(d, new object[] { s });
            }
            else
            {
                this.lblCurrentFile.Text = s;
            }
        }

        private delegate void AddListDelegate(string name, int index, Bitmap bmp);
        private void AddList(string name, int index, Bitmap bmp)
        {
            if (this.listView1.InvokeRequired)
            {
                AddListDelegate d = new AddListDelegate(AddList);
                this.Invoke(d, new object[] { name, index, bmp });
            }
            else
            {
                try
                {
                    this.largeImageList.Images.Add(bmp);
                    this.listView1.Items.Add(name, index);
                }
                catch (Exception) { }
            }
        }

        private delegate void ClearListDelegate();
        private void ClearList()
        {
            if (this.listView1.InvokeRequired)
            {
                ClearListDelegate d = new ClearListDelegate(ClearList);
                this.Invoke(d);
            }
            else
            {
                this.listView1.Clear();
                this.largeImageList.Images.Clear();
            }
        }
    }
}
